package top.zywork.strategy.order;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.zywork.common.DateUtils;
import top.zywork.common.StringUtils;
import top.zywork.dao.AccountDetailDAO;
import top.zywork.dao.GoodsOrderAccountDAO;
import top.zywork.dao.GoodsOrderDAO;
import top.zywork.dao.PlatformAccountDetailDAO;
import top.zywork.dos.*;
import top.zywork.dto.OrderPayDTO;
import top.zywork.dto.RefundOrderDTO;
import top.zywork.enums.*;
import top.zywork.service.DistributionService;
import top.zywork.service.SysConfigService;
import top.zywork.weixin.PayResult;
import top.zywork.weixin.RefundResult;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 针对于后期商城服务
 * @author Animo
 * @Date 2020/10/21
 * @Blog http://www.ljyanimo.com
 */
@Service
public class MallOrderService implements OrderService {

    private static String payNotifyUrl = "/wx-pay/goods-order/wx-pay-notify/" + PayOrderEnum.MALL.getName();

    @Resource
    private GoodsOrderDAO goodsOrderDAO;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private DistributionService distributionService;

    @Resource
    private AccountDetailDAO accountDetailDAO;

    @Resource
    private PlatformAccountDetailDAO platformAccountDetailDAO;

    @Resource
    private GoodsOrderAccountDAO goodsOrderAccountDAO;

    @Override
    public OrderPayDTO orderValidation(String orderId) {
        return null;
    }


    @Override
    public void wxPaySuccessNotify(PayResult payResult) {
        JSONObject attachJsonObj = JSONObject.parseObject(payResult.getAttach());
        Long userId = attachJsonObj.getLong("userId");
        String orderIdAndNos = attachJsonObj.getString("orderIdAndNos");
        String[] orderIdAndNoAry = orderIdAndNos.split(",");
        Long[] orderIdAry = new Long[orderIdAndNoAry.length];
        for (int i = 0, len = orderIdAry.length; i < len; i++) {
            orderIdAry[i] = Long.valueOf(orderIdAndNoAry[i].split("-")[0]);
        }
        List<Object> goodsOrderDOList = new ArrayList<>();
        for (Long orderId : orderIdAry) {
            goodsOrderDOList.add(getGoodsOrderDO(payResult.getTransactionId(), orderId, GoodsOrderStatusEnum.WAIT_DELIVER));
        }
        goodsOrderDAO.updateBatch(goodsOrderDOList);
        BigDecimal amount = new BigDecimal(payResult.getTotalFee() / 100.0).setScale(2, BigDecimal.ROUND_HALF_UP);
        // 只有在成功付款后才会保存用户账目和平台账目
        saveAccountDetail(userId, payResult.getTransactionId(), amount.negate(), orderIdAndNos);
        savePlatformAccountDetail(userId, payResult.getTransactionId(), amount ,orderIdAndNos);
        updateGoodsOrderAccount(orderIdAry, payResult.getTransactionId());
        MallCommissionGrantConfig mallCommissionGrantConfig = sysConfigService.getByName(SysConfigEnum.MALL_COMMISSION_GRANT_CONFIG.getValue(), MallCommissionGrantConfig.class);
        if (mallCommissionGrantConfig.getPayOrder() && !mallCommissionGrantConfig.getConfirmOrder()) {
            distributionService.saveDistributionUserRole(userId, orderIdAry);
            // 明确设置了付款时发放而确认收货时不发放，则发放佣金
            distributionService.grantCommission(userId, orderIdAndNoAry, mallCommissionGrantConfig, null);
        }
    }

    @Override
    public void wxPayFailNotify(PayResult payResult) {
        JSONObject attachJsonObj = JSONObject.parseObject(payResult.getAttach());
        Long[] orderIdAry = StringUtils.strToLongArray(attachJsonObj.getString("orderIds"), ",");
        List<Object> goodsOrderDOList = new ArrayList<>();
        for (Long orderId : orderIdAry) {
            goodsOrderDOList.add(getGoodsOrderDO(payResult.getTransactionId(), orderId, GoodsOrderStatusEnum.PAY_FAILURE));
        }
        goodsOrderDAO.updateBatch(goodsOrderDOList);
    }

    @Override
    public void wxRefundSuccessNotify(RefundResult refundResult) {

    }

    @Override
    public void wxRefundFailNotify(RefundResult refundResult) {

    }

    /**
     * 保存用户账目
     * @param userId
     * @param transactionNo
     * @param amount
     * @param orderIds
     */
    private void saveAccountDetail(Long userId, String transactionNo, BigDecimal amount, String orderIds) {
        AccountDetailDO accountDetailDO = AccountDetailDO.builder()
                .userId(userId)
                .transactionNo(transactionNo)
                .amount(amount)
                .type(IncomeOutgoingTypeEnum.OUTGOING.getValue().byteValue())
                .subType(FundsChangeTypeEnum.MALL_ORDER_OUT.getValue())
                .payType(PaymentTypeEnum.WEIXIN_PAY.getValue().byteValue())
                .accountStatus(AccountStatusEnum.WAIT_CONFIRM.getValue().byteValue())
                .remark("商城订单支出，订单信息：" + orderIds).build();
        accountDetailDAO.save(accountDetailDO);
    }

    @Override
    public RefundOrderDTO refundValidation(String orderId) {
        return null;
    }

    /**
     * 保存平台账目
     * @param userId
     * @param transactionNo
     * @param amount
     * @param orderIds
     */
    private void savePlatformAccountDetail(Long userId, String transactionNo, BigDecimal amount, String orderIds) {
        PlatformAccountDetailDO platformAccountDetailDO = PlatformAccountDetailDO.builder()
                .userId(userId)
                .transactionNo(transactionNo)
                .amount(amount)
                .type(IncomeOutgoingTypeEnum.INCOME.getValue().byteValue())
                .subType(FundsChangeTypeEnum.MALL_ORDER_IN.getValue())
                .payType(PaymentTypeEnum.WEIXIN_PAY.getValue().byteValue())
                .accountStatus(AccountStatusEnum.WAIT_CONFIRM.getValue().byteValue())
                .remark("商城订单收入，订单信息：" + orderIds).build();
        platformAccountDetailDAO.save(platformAccountDetailDO);
    }

    private void updateGoodsOrderAccount(Long[] orderIds, String transactionNo) {
        List<GoodsOrderAccountDO> goodsOrderAccountDOList = new ArrayList<>();
        for (Long orderId : orderIds) {
            goodsOrderAccountDOList.add(GoodsOrderAccountDO.builder().orderId(orderId).transactionNo(transactionNo).build());
        }
        goodsOrderAccountDAO.updateByOrderIds(goodsOrderAccountDOList);
    }

    private GoodsOrderDO getGoodsOrderDO(String transactionNo, Long orderId, GoodsOrderStatusEnum goodsOrderStatusEnum) {
        return GoodsOrderDO.builder()
                .id(orderId)
                .orderStatus(goodsOrderStatusEnum.getValue().byteValue())
                .payTime(DateUtils.currentDate())
                .payType(PaymentTypeEnum.WEIXIN_PAY.getValue().byteValue())
                .transactionNo(transactionNo)
                .paySuccess(goodsOrderStatusEnum == GoodsOrderStatusEnum.PAY_FAILURE ? (byte) 0 : (byte) 1)
                .build();
    }

}
